﻿using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Newtonsoft.Json.Serialization;
using Org.BouncyCastle.Asn1.Ocsp;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;

namespace Jim.Core;

public static class StringExtension
{
    /// <summary>
    /// 判断文本是否为空
    /// </summary>
    /// <param name="str"></param>
    /// <returns></returns>
    public static bool IsNullOrEmpty(this string str)
    {
        return String.IsNullOrEmpty(str);
    }
    /// <summary>
    /// 判断为空不为空
    /// </summary>
    /// <param name="str"></param>
    /// <returns></returns>
    public static bool IsNotNullOrEmpty(this string str) => !str.IsNullOrEmpty();
    /// <summary>
    /// 判断文本是否为空
    /// </summary>
    /// <param name="str"></param>
    /// <returns></returns>
    public static bool IsNullOrWhiteSpace(this string str)
    {
        return String.IsNullOrWhiteSpace(str);
    }

    /// <summary>
    ///  数组拼接文本，默认,分隔
    ///  作者：金朝钱
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="list">带转换数组</param>
    /// <param name="split">分隔字符串，默认,</param>
    /// <returns></returns>
    public static string Join<T>(this IEnumerable<T>? list, string split = ",")
    {
        if (list == null || list.Count() == 0) return "";
        return string.Join(split, list);
    }


    /// <summary>
    /// 字符串转转成驼峰式命名法
    /// 驼峰式命名又叫小驼峰命名法。第一个单词字母小写，后面其他单词首字母大写。
    /// 去掉字符串中[-]
    /// 每个字母的首字母转为大写
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    public static string ToCamelCase(this string input)
    {
        if (string.IsNullOrEmpty(input)) return string.Empty;
        string[] words = input.Split('_');
        StringBuilder sb = new StringBuilder();
        foreach (string word in words)
        {
            sb.Append(char.ToLower(word[0]) + word.Substring(1));
        }
        string camelCase = sb.ToString();
        return camelCase;
    }


    /// <summary>
    /// 获取字符串值
    /// </summary>
    /// <param name="str">传入字符串</param>
    /// <param name="defaultValue">默认值</param>
    /// <returns></returns>
    public static string GetValue(this string? str, string defaultValue = "") => str.IsNullOrEmpty() ? defaultValue : str;

    #region Base64 
    /// <summary>
    /// 文本转Base64
    /// </summary>
    /// <param name="text"></param>
    /// <param name="encoding"></param>
    /// <returns></returns>
    public static string ToBase64(this string text, Encoding? encoding = null)
    {
        byte[] bytes = (encoding ?? Encoding.UTF8).GetBytes(text);
        return ToBase64(bytes);
    }
    /// <summary>
    /// Byte[]转Base64
    /// </summary>
    /// <param name="bytes"></param>
    /// <returns></returns>
    public static string ToBase64(this byte[] bytes)
    {
        string base64String = Convert.ToBase64String(bytes);
        return base64String;
    }
    #endregion


    #region JSON 
    public static string ToJson(this object obj)
    {
        JsonSerializerSettings settings = new JsonSerializerSettings()
        {
            NullValueHandling = NullValueHandling.Ignore,
            DefaultValueHandling = DefaultValueHandling.IgnoreAndPopulate,
            ContractResolver = new CamelCasePropertyNamesContractResolver()
        };
        return JsonConvert.SerializeObject(value: obj, settings);
    }

    public static T FromJson<T>(this string json)
    {
        JsonSerializerSettings settings = new JsonSerializerSettings()
        {
            NullValueHandling = NullValueHandling.Ignore,
            DefaultValueHandling = DefaultValueHandling.IgnoreAndPopulate,
            ContractResolver = new CamelCasePropertyNamesContractResolver()
        };
        settings.Error = (sender, args) =>
        {
            Console.WriteLine($"Error: {args.ErrorContext.Error.Message}");
            args.ErrorContext.Handled = true; // 标记错误已经处理
        };

        return JsonConvert.DeserializeObject<T>(json, settings);
    }

    #endregion


    #region url拼接  
    /// <summary>
    /// url添加请求参数
    /// </summary>
    /// <param name="url"></param>
    /// <param name="key"></param>
    /// <param name="val"></param>
    /// <param name="encode"></param>
    /// <returns></returns>
    public static string AddQueryParam(this string url, string key, object val, bool encode = true)
    {
        var temp = url;
        if (val != null)
        {
            if (val.IsCommonType()) 
                temp = url.AddQueryParam(key, val.ToString(), encode);
            else 
                temp = url.AddQueryParam(key, val.ToJson(), encode);
        }
        return temp;
    }

    /// <summary>
    /// url添加请求参数
    /// </summary>
    /// <param name="url"></param>
    /// <param name="key"></param>
    /// <param name="val"></param>
    /// <param name="encode"></param>
    /// <returns></returns>
    public static string AddQueryParam(this string url, object key, string val, bool encode = true)
    {
        return url.AddQueryParam(key?.ToString(), val, encode);
    }

    /// <summary>
    /// url添加请求参数
    /// </summary>
    /// <param name="url"></param>
    /// <param name="key"></param>
    /// <param name="val"></param>
    /// <param name="encode"></param>
    /// <returns></returns>
    public static string AddQueryParam(this string url, string key, string val, bool encode = true)
    {
        if (url == null)url = "";
        if (key == null || val == null)return url;
        var prefix = string.Empty;
        if (!url.EndsWith("?") && !url.EndsWith("&"))
        {
            prefix = url.IndexOf('?') == -1 ? "?" : "&";
        }
        return url + prefix + key + "=" + (encode ? val.UrlEncode() : val);
    }

    public static string AddQueryParam(this string url, Dictionary<string, object> dic, bool encode = true)
    {
        foreach (var kv in dic)
        {
            url.AddQueryParam(kv.Key, kv.Value, encode);
        }
        return url;
    }
    public static string AddQueryParam(this string url, object obj, bool encode = true)
    {
        var properties = obj.GetType().GetProperties()
            .Where(p => p.GetCustomAttributes(typeof(JsonIgnoreAttribute), true).Length == 0);
        foreach (var property in properties)
        {
            url.AddQueryParam(property.Name.ToCamelCase(), property.GetValue(obj), encode);
        }
        return url;
    }

    #endregion


    public static JToken TryGetToken(this JToken jToken, string propName, out JToken value, bool deleteProp = false)
    {
        value = null;
        if (jToken is JObject jObject)
        {
            if (jObject.ContainsKey(propName))
            {
                value = jObject[propName].DeepClone();
                if (deleteProp)
                {
                    jObject.Remove(propName);
                    return jObject;
                }

                jObject.Remove(propName);
                return jObject;
            }
        }
        return jToken;
    }


    public static JToken TryGetValue<T>(this JToken jToken, string propName, ref T value, T defaultValue = default(T), bool deleteProp = false)
    {
        value = defaultValue;
        if (jToken is JObject jObject)
        {
            if (jObject.ContainsKey(propName))
            {
                try
                {
                    JToken propToken = jObject[propName];
                    //value = propToken.Value<T>();
                    value = propToken.ToObject<T>();
                    if (deleteProp)
                    {
                        jObject.Remove(propName);
                        return jObject;
                    }
                }
                catch (Exception)
                {
                    return jObject;
                }

                jObject.Remove(propName);
                return jObject;
            }
        }
        return jToken;
    }


    public static bool IsJsonString(this string str, ref string json)
    {
        bool isJson = false;
        Regex regex = new Regex(@"{.*?}$"); // 假设只想提取大括号之间的部分
        Match match = regex.Match(str);
        if (match.Success)
        {
            json = match.Value;
            isJson = true;
        }
        return true;
    }

    public static string Right(this long value, int length)
    {
        var str = value.ToString();
        return str.Right(length);
    }

    public static string Right(this string value, int length)
    {
        var lenNow = value.Length;
        if (lenNow <= length) return value;
        else return value.Substring(lenNow - length, length);
    }

}
